<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>热力图3D-立体仓储系统</title>
    <!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>-->
	<link rel="stylesheet" href="css/all.min.css">
	<link rel="stylesheet" href="css/index.css">
    <script src="js/jquery-3.7.1.min.js"></script>
	<script src="ThreeJs/js/three.js"></script>
    <script src="ThreeJs/js/OrbitControls.js"></script>
	<script src="js/data-wms.js"></script>
	<script src="js/index.js"></script>
    <style>
		
        #container {
            position: absolute;
            width: 100%;
            height: 100%;
        }
		
        
        #ui {
            position: absolute;
            top: 60px;
            left: 10px;
            z-index: 100;
            background: rgba(0, 0, 0, 0.7);
            padding: 10px;
            border-radius: 5px;
        }
        
        .control-panel {
            margin-bottom: 15px;
        }
        
        .control-group {
            margin-bottom: 10px;
        }
        
        label {
            display: inline-block;
            width: 80px;
            color: #90e0ef;
        }
        
        select, button {
            background: rgba(255, 255, 255, 0.1);
            border: 1px solid rgba(255, 255, 255, 0.3);
            color: #e6e6e6;
            padding: 5px;
            border-radius: 3px;
        }
        
        button {
            cursor: pointer;
            padding: 5px 10px;
            transition: all 0.3s;
        }
        
        button:hover {
            background: rgba(0, 180, 216, 0.3);
            border-color: #00b4d8;
        }
        
        .legend {
            display: flex;
            flex-direction: column;
            gap: 5px;
            margin-top: 15px;
        }
        
        .legend-item {
            display: flex;
            align-items: center;
        }
        
        .legend-color {
            width: 20px;
            height: 20px;
            margin-right: 10px;
            border: 1px solid #333;
        }
        
        #toggleAnimation {
            position: absolute;
            bottom: 10px;
            left: 10px;
            z-index: 100;
            color: white;
            background: rgba(0, 0, 0, 0.5);
            padding: 5px 10px;
            border-radius: 3px;
            font-size: 12px;
        }
        
        .tooltip {
            position: absolute;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 8px;
            border-radius: 4px;
            pointer-events: none;
            font-size: 14px;
            max-width: 300px;
            z-index: 1000;
            display: none;
        }
        
        .info-panel {
            position: absolute;
            bottom: 2px;
            left: 50%;
            transform: translate(-50%,0);
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 10px;
            border-radius: 6px;
            z-index: 1001;
            display: none;
            width: 300px;
            box-shadow: 0 0 20px rgba(0, 180, 216, 0.5);
            border: 1px solid #00b4d8;
        }
        
        .info-panel h3 {
            margin-top: 0;
            color: #90e0ef;
            border-bottom: 1px solid #00b4d8;
            padding-bottom: 10px;
        }
        
        .info-panel .close-btn {
            position: absolute;
            top: 10px;
            right: 10px;
            cursor: pointer;
            color: #90e0ef;
            font-size: 18px;
        }
        
        .info-content {
            margin-top: 10px;
        }
        
        .info-row {
            display: flex;
            margin-bottom: 5px;
        }
        
        .info-label {
            font-weight: bold;
            color: #90e0ef;
            width: 100px;
        }
        
        .info-value {
            flex: 1;
        }
    </style>
</head>
<body>
	<!-- 导航栏 -->
    <div id="floating-nav">
        <div class="nav-collapsed"></div>
        <div class="nav-content">
            <div class="nav-icon" data-tooltip="库存监控" data-url="wms-3d.html">
                <i class="fas fa-chart-bar"></i>
            </div>
            <div class="nav-icon nav-icon-active" data-tooltip="热力图" data-url="heatmap-3d.html">
                <i class="fas fa-braille"></i>
            </div>
            <div class="nav-icon" data-tooltip="数据同步" data-url="data-sync.html">
                <i class="fas fa-exchange"></i>
            </div>
        </div>
    </div>
	
	<div class="title">
	<div class="summary-container">
        <div class="storage-selector">
            <select id="storageSelect">
                <option value="D">国内存储区</option>
                <option value="I">国际存储区</option>
            </select>
        </div>
		<div class="summary-stats">根据使用次数的热力图</div>
		
		<div class="view-control">
			<a href="heatmap.html"><i title="侧/俯视图" class="fa-solid fa-list"></i></a>
			<i title="三维视图" class="fa-solid fa-cube active"></i>
		</div>
    </div>
		<div class="screen-control" id="fullscreen-component">
			<i class="fas fa-expand fullscreen-toggle" title="进入全屏"></i>
		</div>
	</div>
	

    <div id="container"></div>
    
    <div id="ui">
        <div class="control-panel">
        </div>
    </div>
    
	<button id="toggleAnimation">暂停旋转</button>
	
    <div class="tooltip" id="tooltip"></div>
    
    <div class="info-panel" id="infoPanel">
        <span class="close-btn" id="closeInfoPanel"><i class="fas fa-times"></i></span>
        <h3>库位详细信息</h3>
        <div class="info-content" id="infoContent">
            <!-- Content will be filled dynamically -->
        </div>
    </div>
    
    <script>
		
        
        // 货架配置
        const warehouseConfig = {
            columns: 20,  // X轴 (列)
            levels: 5,    // Y轴 (层)
            rows: 16,     // Z轴 (排)
            cellSize: 1,  // 每个库位的大小
            columnSpacing: 0.1,  // 列之间的间距
            rowSpacing: 1.0      // 排之间的间距
        };
        
        // 初始化Three.js场景
        let scene, camera, renderer, controls;
        let warehouseGroup = new THREE.Group();
        let animationId;
        let isAnimating = true;
        let highlightedCell = null;
        let selectedCell = null;
        
        // 初始化场景
        function init() {
            // 场景
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0x1a1a2e);
            
            // 相机
            camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(15, 20, 15);
            
            // 渲染器
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            //renderer.shadowMap.enabled = true;
            document.getElementById('container').appendChild(renderer.domElement);
            
            // 轨道控制器
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
			
            
            // 灯光
            addLights();
            
            // 仓库模型
            createWarehouse();
            
            // 坐标轴辅助
            //const axesHelper = new THREE.AxesHelper(5);
            //scene.add(axesHelper);
            
            // 事件监听
            window.addEventListener('resize', onWindowResize);
            renderer.domElement.addEventListener('mousemove', onMouseMove);
            renderer.domElement.addEventListener('click', onClick); 
            
            // UI事件
            document.getElementById('toggleAnimation').addEventListener('click', toggleAnimation);
            document.getElementById('closeInfoPanel').addEventListener('click', closeInfoPanel);
            
            // 动画
            animate();
        }
        
        // 添加灯光
        function addLights() {
            // 环境光
            const ambientLight = new THREE.AmbientLight(0x404040);
            scene.add(ambientLight);
            
            // 平行光1
            const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8);
            directionalLight1.position.set(10, 20, 10);
            directionalLight1.castShadow = true;
            directionalLight1.shadow.mapSize.width = 1024;
            directionalLight1.shadow.mapSize.height = 1024;
            scene.add(directionalLight1);
            
            // 平行光2
            const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
            directionalLight2.position.set(-10, 20, -10);
            scene.add(directionalLight2);
        }
        
        // 仓库模型
        function createWarehouse() {
            scene.remove(warehouseGroup);
            warehouseGroup = new THREE.Group();
            
            // 仓库总尺寸
            const totalWidth = warehouseConfig.columns * warehouseConfig.cellSize + 
                             (warehouseConfig.columns - 1) * warehouseConfig.columnSpacing;
            const totalHeight = warehouseConfig.levels * warehouseConfig.cellSize;
            const totalDepth = warehouseConfig.rows * warehouseConfig.cellSize + 
                             (warehouseConfig.rows - 1) * warehouseConfig.rowSpacing;
            
            // 所有库位
            createAllStorageCells();
            
            scene.add(warehouseGroup);
            
        }
                
        // 创建所有库位
        function createAllStorageCells() {
            // 计算使用次数的范围
            const usedTimes = warehouses.map(item => item.usedTimes);
            const minUsage = Math.min(...usedTimes);
            const maxUsage = Math.max(...usedTimes);
            const usageRange = maxUsage - minUsage;
			//算法2拆成2个255
			const midRange =usageRange/2;
            
            for (let x = 1; x <= warehouseConfig.columns; x++) {
                for (let y = 1; y <= warehouseConfig.levels; y++) {
                    for (let z = 1; z <= warehouseConfig.rows; z++) {
						const w=warehouses.find(w => `${w.coordW[0]}-${w.coordW[1]}-${w.coordW[2]}` === `${x}-${y}-${z}`);
                        const spaceNo = w ? w.spaceNo : "";
						if(w){
							const color = new THREE.Color();
							//算法2
							const usedRange=w.usedTimes - minUsage;
							if(usedRange>midRange){
								//渐变从 255,0,0-255,255,0
								const usageRatio = (w.usedTimes - midRange) / (maxUsage-midRange);
								color.setRGB(1, 1-usageRatio, 0);
							}else{
								//渐变从 255,255,0-0,255,0
								//const usageRatio = (w.usedTimes - midRange) / (minUsage-midRange);
								//color.setRGB(1-usageRatio, 1, 0);
								//渐变从 255,255,0-255,255,255
								const usageRatio = (w.usedTimes - midRange) / (minUsage-midRange);
								color.setRGB(1, 1, usageRatio);
							}
							
							// 颜色 (从红到黄渐变)
							//const usageRatio = (w.usedTimes - minUsage) / usageRange;
							////color.setHSL(usageRatio * 0.3, 1, 0.5);
							//color.setRGB(1, 1-usageRatio, 0); //没有等分成255份,差距较大的话效果不明显,按比例分摊到255区间
							
							const cell = createStorageCell(x, y, z, color, w.usedTimes, w.spaceNo);
							//cell.material.opacity = 0.9;
							warehouseGroup.add(cell);
						}else{
							// 空库位（灰色半透明）
                            const cell = createStorageCell(x, y, z, new THREE.Color(0xcccccc), 0, spaceNo);
                            cell.material.transparent = true;
                            cell.material.opacity = 0.2;
                            warehouseGroup.add(cell);
                        }
                    }
                }
            }
        }
        
        // 创建单个库位
        function createStorageCell(x, y, z, color, usedTimes, spaceNo) {
            // 计算位置
            const posX = (x - 1) * (warehouseConfig.cellSize + warehouseConfig.columnSpacing);
            const posY = (y - 1) * warehouseConfig.cellSize; 
            const posZ = (z - 1) * (warehouseConfig.cellSize + warehouseConfig.rowSpacing);
			            			
            // 创建几何体
            const geometry = new THREE.BoxGeometry(
                warehouseConfig.cellSize, 
                warehouseConfig.cellSize, 
                warehouseConfig.cellSize
            );
            
            // 创建材质
            const material = new THREE.MeshPhongMaterial({ 
                color: color,
                transparent: true,
                opacity: 0.8,
                shininess: 30
            });
            
            // 创建网格
            const cube = new THREE.Mesh(geometry, material);
            cube.position.set(posX, posY, -posZ);
            
            // 添加边框
            const line = new THREE.LineSegments(
                new THREE.EdgesGeometry(geometry),
                new THREE.LineBasicMaterial({ color: 0x000000, linewidth: 1 })
            );
            cube.add(line);
            
            // 存储自定义数据
            cube.userData = {
                spaceNo: spaceNo,
                usedTimes: usedTimes,
                color: color,
                originalColor: color.clone(),
                originalMaterial: material,
                coordX: x,
                coordY: y,
                coordZ: z
            };
            
            return cube;
        }
                
        // 切换动画状态
        function toggleAnimation() {
            isAnimating = !isAnimating;
            document.getElementById('toggleAnimation').textContent = isAnimating ? '暂停旋转' : '开始旋转';
        }
        
        // 关闭信息面板
        function closeInfoPanel() {
            document.getElementById('infoPanel').style.display = 'none';
            
            // 恢复选中库位的颜色
            if (selectedCell) {
                selectedCell.material.color.copy(selectedCell.userData.originalColor);
                selectedCell = null;
            }
        }
        
        // 显示库位详细信息
        function showCellInfo(cell) {
            const infoPanel = document.getElementById('infoPanel');
            const infoContent = document.getElementById('infoContent');
            
            infoContent.innerHTML = `
                <div class="info-row">
                    <div class="info-label">库位编号:</div>
                    <div class="info-value">${cell.userData.spaceNo}</div>
                </div>
                <div class="info-row">
                    <div class="info-label">坐标位置:</div>
                    <div class="info-value">${cell.userData.coordX}-${cell.userData.coordY}-${cell.userData.coordZ} (列-层-排)</div>
                </div>
                <div class="info-row">
                    <div class="info-label">使用次数:</div>
                    <div class="info-value">${cell.userData.usedTimes || '无数据'}</div>
                </div>
            `;
            
            // 显示面板
            infoPanel.style.display = 'block';
        }
        
        // 鼠标移动事件
        function onMouseMove(event) {
            event.preventDefault();
    
			const mouse = new THREE.Vector2();
			mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
			mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
			
			const raycaster = new THREE.Raycaster();
			raycaster.setFromCamera(mouse, camera);
			
			const intersects = raycaster.intersectObjects(warehouseGroup.children, true);
			
			if (highlightedCell && highlightedCell !== selectedCell) {
				highlightedCell.material.color.copy(highlightedCell.userData.originalColor);
				highlightedCell = null;
				document.getElementById('tooltip').style.display = 'none';
			}
			
			for (let i = 0; i < intersects.length; i++) {
				const object = intersects[i].object;
				
				// 检查是否是库位立方体(不是线框)
				if (object instanceof THREE.Mesh && 
					object.geometry instanceof THREE.BoxGeometry && 
					object.userData.spaceNo) {
					
					// 跳过已选中的库位
					if (object === selectedCell) continue;
					
					highlightedCell = object;
					highlightedCell.material.color.set(0x00ffff);
					
					// 显示tooltip
					const tooltip = document.getElementById('tooltip');
					tooltip.style.display = 'block';
					tooltip.style.left = `${event.clientX + 15}px`;
					tooltip.style.top = `${event.clientY + 15}px`;
					tooltip.innerHTML = `
						<div><strong>库位编号:</strong> ${highlightedCell.userData.spaceNo}</div>
						<div><strong>使用次数:</strong> ${highlightedCell.userData.usedTimes}</div>
						<div><strong>点击查看详情</strong></div>
					`;
					
					break;
				}
			}
        }
        
        // 鼠标点击事件
        function onClick(event) {
			console.log('111');
            event.preventDefault();
    
			// 计算鼠标位置归一化坐标
			const mouse = new THREE.Vector2();
			mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
			mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
			
			// 创建射线
			const raycaster = new THREE.Raycaster();
			raycaster.setFromCamera(mouse, camera);
			
			// 计算相交对象 - 现在会检测所有子对象
			const intersects = raycaster.intersectObjects(warehouseGroup.children, true);
			
			if (intersects.length > 0) {
				// 找到第一个是Mesh的对象（跳过可能的线框）
				let firstIntersect = null;
				for (let i = 0; i < intersects.length; i++) {
					if (intersects[i].object instanceof THREE.Mesh && intersects[i].object.userData.spaceNo) {
						firstIntersect = intersects[i].object;
						break;
					}
				}
				
				if (firstIntersect) {
					// 如果点击的是已选中的库位，则关闭面板
					if (selectedCell === firstIntersect) {
						closeInfoPanel();
						return;
					}
					
					// 恢复之前选中库位的颜色
					if (selectedCell) {
						selectedCell.material.color.copy(selectedCell.userData.originalColor);
					}
					
					// 设置新选中的库位
					selectedCell = firstIntersect;
					selectedCell.material.color.set(0x00ff00); // 绿色表示选中
					
					// 显示详细信息面板
					showCellInfo(selectedCell);
				}
			} else {
				// 点击空白处关闭信息面板
				closeInfoPanel();
			}
        }
        
        // 窗口大小调整
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }
        
        // 动画循环
        function animate() {
            animationId = requestAnimationFrame(animate);
            
            // 自动旋转
            if (isAnimating) {
                warehouseGroup.rotation.y += 0.002;
            }
            
            controls.update();
            renderer.render(scene, camera);
            
        }
        
		$(function() {
			
			init();
			
        });
    </script>
</body>
</html>